/*
 * This file is part of the OpenKinect Project. http://www.openkinect.org
 *
 * Copyright (c) 2010 Brandyn White (bwhite@dappervision.com)
 *
 * This code is licensed to you under the terms of the Apache License, version
 * 2.0, or, at your option, the terms of the GNU General Public License,
 * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses,
 * or the following URLs:
 * http://www.apache.org/licenses/LICENSE-2.0
 * http://www.gnu.org/licenses/gpl-2.0.txt
 *
 * If you redistribute this file in source form, modified or unmodified, you
 * may:
 *   1) Leave this header intact and distribute it under the same terms,
 *      accompanying it with the APACHE20 and GPL20 files, or
 *   2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or
 *   3) Delete the GPL v2 clause and accompany it with the APACHE20 file
 * In all cases you must keep the copyright notice intact and include a copy
 * of the CONTRIB file.
 *
 * Binary distributions must follow the binary distribution requirements of
 * either License.
 */

#include "fakenect.h"


static void sleep_highres(double tm){
        int sec = floor(tm);
        int usec = (tm - sec) * 1000000;
        if (tm > 0) {
                sleep(sec);
                usleep(usec);
        }
}
static double get_time(){
        struct timeval cur;
        gettimeofday(&cur, NULL);
        return cur.tv_sec + cur.tv_usec / 1000000.;
}

void recv_frm_socket(int socket, unsigned char **recv_buf, int size){
	int numbytes=0;
//printf("writing at add=%d\n",*recv_buf);
    if ((numbytes = recv(socket, *recv_buf, size,0)) != -1) {
		if(numbytes==0){
			printf("Error: numbytes received=0 for size=%d socket=%d \n",size,socket);
			exit(-1);
		}
		// attempt to reobtain data which is lost
		while(numbytes<size){
			if(recv(socket,*recv_buf+numbytes,size-numbytes,MSG_PEEK)!=-1)
				numbytes=numbytes+recv(socket,*recv_buf+numbytes,size-numbytes,0);
			else
				printf("Error : no data to read in socket\n");
		}
    }
}

static int recv_a(double *cur_time, uint32_t *timestamp, uint32_t *data_size, char **data,int sockfd1){
//printf("In recv_a\n");
        freenect_raw_tilt_state* state;
        temp_timestamp[TIMESTAMP_BYTES]="";
        temp_cur_time[CUR_TIME_BYTES]="";

        recv_frm_socket(sockfd1,&temp_timestamp,TIMESTAMP_BYTES);
		*timestamp=(unsigned int)atol(temp_timestamp);

		recv_frm_socket(sockfd1,&temp_cur_time,CUR_TIME_BYTES);
		*cur_time=atof(temp_cur_time);

		*data_size = sizeof(*state);
        *data = malloc(*data_size);
		recv_frm_socket(sockfd1,(unsigned char **)data,*data_size);

//printf("Received Accel DATA..!!!!!timestamp=%u_cur_time=%f\n\n\n",*timestamp,*cur_time);
//printf("Exiting recv_a\n");
        return 0;
}

void call_ffmpeg(int is_Depth){
	int argc=4;
	char *argv[argc];
	argv[0]="../ffmpeg-0.7-rc1/./ffmp";
	argv[1]="-i";
	argv[2]="try.mp4";
	if(is_Depth)
		argv[3]="o%3d.pgm";
	else
		argv[3]="o%3d.ppm";
	isDepth=is_Depth;
	myffmpeg(argc,argv);
	if(isDepth)
		output=output-(FREENECT_DEPTH_11BIT_SIZE*FRAMES_TO_DECODE/2);
	else
		output=output-FREENECT_VIDEO_RGB_SIZE*FRAMES_TO_DECODE;
	return NULL;
}

void *thread_recvfunc(int sockfd3)
{
	int numbytes;
	while(cur_rgb_cb && rgb_running){
printf("TAG________________________ RecvP thread waiting for decompression thread\n");
		pthread_mutex_lock(&decompressed_prev_mutex);
		while(!decompressed_prev)
			pthread_cond_wait(&decompressed_prev_cond,&decompressed_prev_mutex);
		decompressed_prev=0;
		pthread_mutex_unlock(&decompressed_prev_mutex);
//                      printf("recv thread waiting for decompression of prev packet\n");
		if ((numbytes = recv(sockfd3, buf,headerSize , 0)) != -1) {
			// attempt to reobtain header which is lost
printf("TAG____________________wait ended Receiving PACKET HEADER\n");
			while(numbytes<headerSize){
						if(recv(sockfd3,buf+numbytes,headerSize-numbytes,MSG_PEEK)!=-1)
								numbytes=numbytes+recv(sockfd3,buf+numbytes,headerSize-numbytes,0);
						else
								printf("Error recv: no headerData to read\n");
			}
printf(" TAG________________________ GOT PACKET header of size=%d\n",numbytes);
// now recv rgb video
			unsigned char tmp_video_size[VIDEO_HEADER_BYTES]="";
			memcpy(tmp_video_size,buf+headerSize-VIDEO_HEADER_BYTES,VIDEO_HEADER_BYTES);
			unsigned int rgb_video_size=atol(tmp_video_size);
			numbytes=0;
			while(numbytes<rgb_video_size+VIDEO_HEADER_BYTES){
				if(recv(sockfd3,buf+headerSize+numbytes,rgb_video_size+VIDEO_HEADER_BYTES-numbytes,MSG_PEEK)!=-1)
					numbytes=numbytes+recv(sockfd3,buf+headerSize+numbytes,rgb_video_size+VIDEO_HEADER_BYTES-numbytes,0);
				else
					printf("Error RGB recv: no rgbData to read\n");
			}
printf(" TAG________________________ GOT PACKET rgbvideo of size=%d\n",numbytes);

//now recv depth video
			tmp_video_size[VIDEO_HEADER_BYTES]="";
			memcpy(tmp_video_size,buf+headerSize+rgb_video_size,VIDEO_HEADER_BYTES);
			unsigned int depth_video_size=atol(tmp_video_size);
			numbytes=0;
			while(numbytes<depth_video_size){
				if(recv(sockfd3,buf+headerSize+rgb_video_size+VIDEO_HEADER_BYTES+numbytes,depth_video_size-numbytes,MSG_PEEK)!=-1)
					numbytes=numbytes+recv(sockfd3,buf+headerSize+rgb_video_size+VIDEO_HEADER_BYTES+numbytes,depth_video_size-numbytes,0);
				else
					printf("Error Depth recv: no depthData to read\n");
			}
			printf(" TAG________________________ GOT PACKET depthvideo of size=%d\n",depth_video_size);

			pthread_mutex_lock(&recvd_mutex);
			received=1;
			pthread_cond_signal(&recv_cond);
			pthread_mutex_unlock(&recvd_mutex);

			pthread_mutex_lock(&decompressed_prev_mutex);
			decompressed_prev=0;
            pthread_mutex_unlock(&decompressed_prev_mutex);
		}
	}
	printf("ttt...EXITING recv thread\n");
}
void *thread_decompressfunc(int sockfd3)
{
	pthread_t thread_recv_tid;
    received=0;
    decompressed_prev=1;
    int res=pthread_create(&thread_recv_tid, NULL, thread_recvfunc, sockfd3);
    if (res) {
    	printf("pthread_create for rgb failed\n");
        exit(1);
    }
    unsigned char temp_timestamp[TIMESTAMP_BYTES]="";
    unsigned char temp_record_cur_time[CUR_TIME_BYTES]="";
    unsigned char temp_video_size[VIDEO_HEADER_BYTES]="";
    int numbytes,i=0;
    thread_recv_running=1;

    while(thread_recv_running){
printf("Decompress thread waiting for recv thread\n");
    	pthread_mutex_lock(&recvd_mutex);
        while(!received)
        	pthread_cond_wait(&recv_cond,&recvd_mutex);
        received=0;
		pthread_mutex_unlock(&recvd_mutex);
printf("Decompress thread wait over for recv thread\n");
		flag_back=!flag_back;
printf("started with flag_back=%d_\n\n",flag_back);
        for(i=0;i<FRAMES_TO_DECODE;i++){
        	//printf("original timestamps_%d_%s\n",*(timestamp),temp_timestamp);
	        	memcpy(temp_timestamp,buf+i*(TIMESTAMP_BYTES+CUR_TIME_BYTES),TIMESTAMP_BYTES);
        	//printf("written timestamps_%lu_%s\n",*(timestamp),temp_timestamp);
	            memcpy(temp_record_cur_time,buf+i*(TIMESTAMP_BYTES+CUR_TIME_BYTES)+TIMESTAMP_BYTES,CUR_TIME_BYTES);
printf("TAG>>>>>>>>GOT RGB DATA...=%s__ \n",temp_record_cur_time);
            if(flag_back){
            	array_record_cur_time_back[i]=atof(temp_record_cur_time);
				array_timestamp_back[i]=strtoul (temp_timestamp,NULL,0);;
printf("TAG========GOT RGB DATA...=%f_%f_ \n",array_record_cur_time_back[i],array_record_cur_time_back[3]);
            }
            else{
            	array_record_cur_time_front[i]=atof(temp_record_cur_time);
				array_timestamp_front[i]=strtoul (temp_timestamp,NULL,0);;
            }
//printf("written cur_time_%f_%s\n",*(cur_time),temp_cur_time);
  printf("array_record_cur_time=%d_front=%d_back=%d\n",array_record_cur_time,array_record_cur_time_front,array_record_cur_time_back);
        }
        memcpy(temp_video_size,buf+FRAMES_TO_DECODE*(TIMESTAMP_BYTES+CUR_TIME_BYTES),VIDEO_HEADER_BYTES);
        unsigned int rgb_video_size=atol(temp_video_size);
//printf("got video header=%d\n",video_size);
//        temp_video_size[VIDEO_HEADER_BYTES]="";
//        memcpy(temp_video_size,buf+FRAMES_TO_DECODE*(TIMESTAMP_BYTES+CUR_TIME_BYTES)+VIDEO_HEADER_BYTES+rgb_video_size,VIDEO_HEADER_BYTES);
//        unsigned int depth0_video_size=atol(temp_video_size);
//printf("TAG________________________operating on myvideo=%d...allocated_rgb_video_size=%d_depthvs=%d\n",myvideo,rgb_video_size,depth0_video_size);

        myvideo=malloc(rgb_video_size);
printf("TAG____________________operating on rgbData=%d_depthData=%d...allocated_rgb_video_size=%d\n",rgbData,depthData,rgb_video_size);
        memcpy(myvideo,buf+FRAMES_TO_DECODE*(TIMESTAMP_BYTES+CUR_TIME_BYTES)+VIDEO_HEADER_BYTES,rgb_video_size);

//printf("got video\n");
//printf("decoding...\n");
        videoSize=rgb_video_size;

double ft=get_time();
        int childpid=fork();
printf("TAG________________________ fork cost=%f\n",get_time()-ft);
        if(childpid<0){
        	perror("Fork Failed");
            exit(1);
        }
        else if(childpid == 0) {// child process
printf("TAG_______________before Calling rgb ffmpeg.............output=%d_outputRgb_front=%d_outputRgb_back=%d\n",output,outputRgb_front,outputRgb_back);
        	if(flag_back)
        		output=outputRgb_back;
        	else
        		output=outputRgb_front;
printf("TAG________________________Calling rgb ffmpeg.............output=%d_outputRgb_front=%d_outputRgb_back=%d\n",output,outputRgb_front,outputRgb_back);
        	call_ffmpeg(0);
//        	free(myvideo);
printf("TAG________________________####EXITING RGB######\n");
            exit(0);
        }
        free(myvideo);
        temp_video_size[VIDEO_HEADER_BYTES]="";
        memcpy(temp_video_size,buf+FRAMES_TO_DECODE*(TIMESTAMP_BYTES+CUR_TIME_BYTES)+VIDEO_HEADER_BYTES+rgb_video_size,VIDEO_HEADER_BYTES);

        unsigned int depth_video_size=atol(temp_video_size);
//printf("TAG________________________ keydepth=%d_depthvideo_size=%d_rgbvideosize=%d\n",keydepth,depth_video_size,rgb_video_size);

        myvideo=malloc(depth_video_size);
printf("TAG_________________operating on depth_rgbData=%d_depthData=%d allocated_rgbvideosize=%d_outputDepth_front=%d\n",rgbData,depthData,rgb_video_size,outputDepth_front);
        memcpy(myvideo,buf+FRAMES_TO_DECODE*(TIMESTAMP_BYTES+CUR_TIME_BYTES)+VIDEO_HEADER_BYTES+rgb_video_size+VIDEO_HEADER_BYTES,depth_video_size);

        pthread_mutex_lock(&decompressed_prev_mutex);
		decompressed_prev=1;
		pthread_cond_signal(&decompressed_prev_cond);
		pthread_mutex_unlock(&decompressed_prev_mutex);

        videoSize=depth_video_size;

        childpid=fork();
printf("TAG________________________ fork cost=%f\n",get_time()-ft);
        if(childpid<0){
        	perror("Fork Failed");
            exit(1);
        }
        else if(childpid == 0) {// child process for depth decompression
printf("TAG__________________before Calling depth ffmpeg.............output=%d_front=%d_back=%d\n",output,outputDepth_front,outputDepth_back);
        	if(flag_back)
        		output=outputDepth_back;
        	else
        		output=outputDepth_front;
printf("TAG________________________Calling depth ffmpeg.............output=%d_front=%d_back=%d\n",output,outputDepth_front,outputDepth_back);
        	call_ffmpeg(1);
 //       	memcpy(outputDepth_front,output,(FREENECT_DEPTH_11BIT_SIZE*FRAMES_TO_DECODE/2));
printf("TAG________________________####EXITING DEPTH######\n");

//        	free(myvideo);
            exit(0);
        }
double t=get_time();
printf("TTT........waitingggg......%f\n",t);
		int status;
		wait(&status);
printf("TTT.........wait done =%f\n",get_time()-t);
		wait(&status);
printf("TTT.........wait done =%f\n",get_time()-t);
printf("TAG________________________........wait done......%f\n",get_time()-t);
printf("TAG________________________....total cost=%f..\n",get_time()-ft);
printf("decompression thread waiting for display_prev\n");

		pthread_mutex_lock(&displayed_prev_mutex);
		while(!displayed_prev)
			pthread_cond_wait(&displayed_prev_cond,&displayed_prev_mutex);
		displayed_prev=0;
		pthread_mutex_unlock(&displayed_prev_mutex);
printf("decompression thread wait ended for display_prev\n");

//		output = output- FRAMES_TO_DECODE*FREENECT_VIDEO_RGB_SIZE;
		if(flag_back){
			array_timestamp=&array_timestamp_back;
			array_record_cur_time=&array_record_cur_time_back;
//			memcpy(rgbData,outputRgb_back,FRAMES_TO_DECODE*(FREENECT_VIDEO_RGB_SIZE));
			rgbData=outputRgb_back;
			depthData=outputDepth_back;
//printf("TAG________________________GOT RGB DATA...=%d_%d_%f_%f_ \n",rgbData,array_record_cur_time,*array_record_cur_time,*(array_record_cur_time+3));
//printf("TAG========GOT RGB DATA...=%d_%d_%f_%f \n",rgbData,array_record_cur_time_back,array_record_cur_time_back[0],array_record_cur_time_back[3]);
//printf("TAG________________________GOT RGB DATA...=%d_%d_%d_%d_ \n",rgbData,array_record_cur_time,*array_record_cur_time,*(array_record_cur_time+3));
		}else{
			array_timestamp=&array_timestamp_front;
			array_record_cur_time=&array_record_cur_time_front;
//			memcpy(rgbData,outputRgb_front,FRAMES_TO_DECODE*(FREENECT_VIDEO_RGB_SIZE));
			rgbData=outputRgb_front;
			depthData=outputDepth_front;
		}
printf("TAG________________________GOT RGB DATA...=%d_\n",rgbData);
		//	if(flag_back)
//			rgbData=outputRgb_back;
//		else
//			rgbData=outputRgb_front;
//		memcpy(depthData,outputDepth,FRAMES_TO_DECODE*(FREENECT_DEPTH_11BIT_SIZE/2));
printf("TAG________________________GOT DEPTH DATA=%d \n",depthData);

//printf("decoding done\n");
//printf("------Received DATA RGB..!!!!!bytes=%d_timestamp=%s_%u_cur_time=%s_%f\n\n\n",numbytes,temp_timestamp,*timestamp,temp_cur_time,*cur_time);
free(myvideo);

		pthread_mutex_lock(&decompressed_mutex);
		decompressed=1;
		pthread_cond_signal(&decompressed_cond);
		pthread_mutex_unlock(&decompressed_mutex);
printf("TAG________________________####DEcompression done######\n");

    }
	thread_decompress_running=0;
printf("ttt...decompress thread EXITING \n");
	pthread_exit(0);
}

void *thread_displayfunc(int sockfd3)
{
 //printf("T1 sockfd3=%d\n",sockfd3);
        pthread_t thread_decompress_tid;
        decompressed=0;
        displayed_prev=1;
        int res=pthread_create(&thread_decompress_tid, NULL, thread_decompressfunc, sockfd3);
        if (res) {
                printf("pthread_create for rgb failed\n");
                exit(1);
        }
        thread_decompress_running=1;
        while(thread_decompress_running){
                int wait_time=get_time();
printf("DISPLAY THREAD____chckpt...Display thread waiting for decompression thread\n");
                pthread_mutex_lock(&decompressed_mutex);
                while(!decompressed)
					pthread_cond_wait(&decompressed_cond,&decompressed_mutex);
                decompressed=0;
				pthread_mutex_unlock(&decompressed_mutex);
printf("DISPLAY THREAD____chckpt...wait time =%f\n\n",get_time()-wait_time);
                int j,numbytes;
                for(j=0;j<FRAMES_TO_DECODE;j++){
//printf("ttt..entered_!!!!!\n");
printf("\nDISPLAY THREAD____started=%d_rgbData=%d_depthData=%d\n\n",j,rgbData,depthData);
printf("TAG========...=%f__%d \n",*(array_record_cur_time+j),array_record_cur_time);
                        if (record_prev_time != 0. && playback_prev_time != 0.){
                                double tm=(*(array_record_cur_time+j) - record_prev_time) - (get_time() - playback_prev_time);
//printf("ttt...chckpt...sleeping for %f_%f_\n",tm,*(array_record_cur_time+j));
                               sleep_highres(tm);
//printf("ttt...chckpt...woke for %f_%f_\n",tm,*(array_record_cur_time+j));
                        }
                        record_prev_time = *(array_record_cur_time+j);
//printf("ttt..checkpoint_tmp_rgb=%d\n",tmp_rgb);
printf("DISPLAY THREAD____got header=%d_rgbData=%d_depthData=%d\n",j,rgbData,depthData);
                        tmp_rgb=rgbData+j*FREENECT_VIDEO_RGB_SIZE;
/*printf("latency_r_%d_%c\n",rgbData[(2*j+1)*FREENECT_VIDEO_RGB_SIZE/2]);
printf("latency_g_%d_%c\n",rgbData[(2*j+1)*(FREENECT_VIDEO_RGB_SIZE/2)+1]);
printf("latency_b_%d_%c\n",rgbData[(2*j+1)*(FREENECT_VIDEO_RGB_SIZE/2)+2]);
*/
//						tmp_rgb=RED;
//printf("ttt..Done copying_!!!!!rgb_buffer=%d_tmp_rgb=%d\n",rgb_buffer,tmp_rgb);
                        if (rgb_buffer) {
                                memcpy(rgb_buffer, tmp_rgb, FREENECT_VIDEO_RGB_SIZE);
                                tmp_rgb = rgb_buffer;
                        }
//printf("ttt..calling cur_rgb_cb...\n");
                        cur_rgb_cb(fake_dev, tmp_rgb, *(array_timestamp+j));
                        playback_prev_time = get_time();
printf("DISPLAY THREAD____got rgb=%d_rgbData=%d_depthData=%d\n",j,rgbData,depthData);
                        tmp_depth=depthData+j*FREENECT_DEPTH_11BIT_SIZE/2;
						if (depth_buffer) {
//printf("before memcpy\n");
								memcpy(depth_buffer, tmp_depth, FREENECT_DEPTH_11BIT_SIZE/2);
								tmp_depth = depth_buffer;
						}
						cur_depth_cb(fake_dev, tmp_depth, *(array_timestamp+j));
printf("DISPLAY THREAD____got depth=%d_rgbData=%d_depthData=%d\n",j,rgbData,depthData);
                }
printf("DISPLAY THREAD____displayed all frames..setting displayed_prev\n");
 				pthread_mutex_lock(&displayed_prev_mutex);
                displayed_prev=1;
                pthread_cond_signal(&displayed_prev_cond);
				pthread_mutex_unlock(&displayed_prev_mutex);
        }
        thread_display_running=0;
printf("DISPLAY THREAD____ EXITING \n");
        pthread_exit(0);
}
void destroy_shmsegments(){
		shmdt(outputRgb_front);
		shmdt(outputRgb_back);
		shmdt(outputDepth_front);
		shmdt(outputDepth_back);
		shmctl(shmidRgb_front, IPC_RMID, NULL);
		shmctl(shmidRgb_back, IPC_RMID, NULL);
		shmctl(shmidDepth_front, IPC_RMID, NULL);
		shmctl(shmidDepth_back, IPC_RMID, NULL);
}
void signal_handler(int sig){
	if(sig = SIGINT){
		printf("----------********CAUGHT signal cntrl + c, cleaning up ********-----------\n");
		destroy_shmsegments();
		thread_recv_running=0;
		thread_decompress_running=0;
		thread_display_running=0;
	}
}
void init_signals(){
	sigact.sa_handler = signal_handler;
	sigemptyset(&sigact.sa_mask);
	sigact.sa_flags = 0;
	sigaction(SIGINT,&sigact,NULL);
}
void init_shm_seg(int *key, char * path, int *shmid, const int size, unsigned char **shared_seg){
	if((*key = ftok(path,'R'))==-1){
		printf("Error key for path=%s\n",path);
		perror("key not generated");
	}
//printf("TAG________________________ key=%d\n",*key);
	if((*shmid = shmget(*key,size , 0644 | IPC_CREAT))==-1){
		printf("Failed to shmget error = %s for path=%s\n",strerror(errno),path);
		if(errno == EINVAL)
			printf("Invalid segment size specified\n");
		else if(errno == EEXIST)
			printf("Segment exists, cannot create it\n");
		else if(errno == EIDRM)
			printf("Segment is marked for deletion or was removed\n");
		else if(errno == ENOENT)
			printf("Segment does not exist\n");
		else if(errno == EACCES)
			printf("Permission denied\n");
		else if(errno == ENOMEM)
			printf("Not enough memory to create segment\n");
	}
	*shared_seg = shmat(*shmid, (void *)0, 0);
	if(*shared_seg == (int *)(-1)){
		printf("Error shmat for path=%s",path);
		perror("shmat:shared seg attach failed");
	}
}
int freenect_process_events(freenect_context *ctx,int sockfd1,int sockfd2, int sockfd3,int sockfd4)
{
        /* This is where the magic happens. We read 1 update from the index
           per call, so this needs to be called in a loop like usual.  If the
           index line is a Depth/RGB image the provided callback is called.  If
           the index line is accelerometer data, then it is used to update our
           internal state.  If you query for the accelerometer data you get the
           last sensor reading that we have.  The time delays are compensated as
           best as we can to match those from the original data and current run
           conditions (e.g., if it takes longer to run this code then we wait less).
         */
        char type='x';
        double record_cur_time;
        uint32_t timestamp, data_size,last_timestamp;
        char *data = NULL;
        int numbytes;
//----
//              fcntl(sockfd4,F_SETFL,fcntl(sockfd4,F_GETFL,0) | O_NONBLOCK);   // Add non-blocking flag

//printf("Inside freenect process events\n");
        if ((numbytes = recv(sockfd4, &type, 1, 0)) != -1 ) {
//printf("GOT D_%c_%d\n",type,numbytes);
			if(numbytes==0){
				printf("Control Socket Empty=%c\n",type);
				free(data);
				return 0;
			}
        }
        else{
                perror("REcv Error  ACK:sockfd4");
                return -1;
        }

        // Sleep an amount that compensates for the original and current delays
        // playback_ is w.r.t. the current time
        // record_ is w.r.t. the original time period during the recording
//      if (record_prev_time != 0. && playback_prev_time != 0.)
//              sleep_highres((record_cur_time - record_prev_time) - (get_time() - playback_prev_time));
//      record_prev_time = record_cur_time;
//type='c';
//printf("Inside switch_with type=%c\n",type);
        switch (type) {
                case 'd':
/*                        if (recv_d(&record_cur_time, &timestamp, &data_size, &data,sockfd2))
                                return -1;
                        if (cur_depth_cb && depth_running) {
                                void *cur_depth =(void*) data;
                                if (depth_buffer) {
                                        memcpy(depth_buffer, cur_depth, FREENECT_DEPTH_11BIT_SIZE);
                                        cur_depth = depth_buffer;
                                }
                                cur_depth_cb(fake_dev, cur_depth, timestamp);
                        }
*/
                        printf("#####################################SHOULD NOT BE HERE######\n\n\n");
                        break;
                case 'r':
                        printf("#####################################SHOULD NOT BE HERE######\n\n\n");
                        break;
                case 'a':
//printf("Entering______ switch a\n");
                        if (recv_a(&record_cur_time, &timestamp, &data_size, &data,sockfd1))
                                return -1;
                        if (data_size == sizeof(state)) {
                                memcpy(&state, data, sizeof(state));
//printf(">>>>>>>>>>>>>>>>>>>GOT a_angle=%f\n",freenect_get_tilt_degs(&state));
                        } else if (!already_warned) {
                                already_warned = 1;
                                printf("\n\nWarning: Accelerometer data has an unexpected"
                                       " size [%u] instead of [%u].  The acceleration "
                                       "and tilt data will be substituted for dummy "
                                       "values.  This data was probably made with an "
                                       "older version of record (the upstream interface "
                                       "changed).\n\n",
                                       data_size, (unsigned int)sizeof state);
                        }
                        break;
                case 'b':
                        // dummy call to handle angle request
printf("handling angle request\n");
                        break;
        }
        if (!thread_display_running && cur_rgb_cb && rgb_running) {
printf("Entering______ switch r\n");

			key_t keyrgb_front;
			init_shm_seg(&keyrgb_front,"glpclview",&shmidRgb_front,FRAMES_TO_DECODE*FREENECT_VIDEO_RGB_SIZE,&outputRgb_front);
			key_t keyrgb_back;
			init_shm_seg(&keyrgb_back,"tiltdemo",&shmidRgb_back,FRAMES_TO_DECODE*FREENECT_VIDEO_RGB_SIZE,&outputRgb_back);
			key_t keydepth_front;
			init_shm_seg(&keydepth_front,"cppview",&shmidDepth_front,FRAMES_TO_DECODE*(FREENECT_DEPTH_11BIT_SIZE/2),&outputDepth_front);
			key_t keydepth_back;
			init_shm_seg(&keydepth_back,"glview",&shmidDepth_back,FRAMES_TO_DECODE*(FREENECT_DEPTH_11BIT_SIZE/2),&outputDepth_back);
			init_signals();
//			rgbData=malloc(FRAMES_TO_DECODE* FREENECT_VIDEO_RGB_SIZE);
//			depthData=malloc(FRAMES_TO_DECODE*(FREENECT_DEPTH_11BIT_SIZE/2));

			int k=0;
			for(;k<FREENECT_VIDEO_RGB_SIZE;k=k+3){
				RED[k]=(char)255;
				RED[k+1]=(char)0;
				RED[k+2]=(char)0;
			}

			pthread_t thread_display_tid;
			int res=pthread_create(&thread_display_tid, NULL, thread_displayfunc, sockfd3);
			if (res) {
					printf("pthread_create for rgb failed\n");
					exit(1);
			}
			thread_display_running=1;
//			printf("ttt parent continuing\n");
//			destroy_shmsegments();
        }
        free(data);
        return 0;
}

double freenect_get_tilt_degs(freenect_raw_tilt_state *state)
{
        // NOTE: This is duped from tilt.c, this is the only function we need from there
        return ((double)state->tilt_angle) / 2.;
}

freenect_raw_tilt_state* freenect_get_tilt_state(freenect_device *dev)
{
        return &state;
}

void freenect_get_mks_accel(freenect_raw_tilt_state *state, double* x, double* y, double* z){
        //the documentation for the accelerometer (http://www.kionix.com/Product%20Sheets/KXSD9%20Product%20Brief.pdf)
        //states there are 819 counts/g
        *x = (double)state->accelerometer_x/FREENECT_COUNTS_PER_G*GRAVITY;
        *y = (double)state->accelerometer_y/FREENECT_COUNTS_PER_G*GRAVITY;
        *z = (double)state->accelerometer_z/FREENECT_COUNTS_PER_G*GRAVITY;
}

void freenect_set_depth_callback(freenect_device *dev, freenect_depth_cb cb){
        cur_depth_cb = cb;
}

void freenect_set_video_callback(freenect_device *dev, freenect_video_cb cb){
        cur_rgb_cb = cb;
}

int freenect_num_devices(freenect_context *ctx){
        // Always 1 device
        return 1;
}

int freenect_open_device(freenect_context *ctx, freenect_device **dev, int index){
        // Set it to some number to allow for NULL checks
        *dev = fake_dev;
        return 0;
}

int freenect_init(freenect_context **ctx, freenect_usb_context *usb_ctx){
        *ctx = fake_ctx;
        return 0;
}

int freenect_set_depth_buffer(freenect_device *dev, void *buf){
        depth_buffer = buf;
        return 0;
}

int freenect_set_video_buffer(freenect_device *dev, void *buf){
        rgb_buffer=buf;
//        printf("ttt....setting_rgb_buffer=%d\n",rgb_buffer);
        return 0;
}

void freenect_set_user(freenect_device *dev, void *user)
{
        user_ptr = user;
}

void *freenect_get_user(freenect_device *dev)
{
        return user_ptr;
}

int freenect_start_depth(freenect_device *dev)
{
        depth_running = 1;
        return 0;
}

int freenect_start_video(freenect_device *dev)
{
        rgb_running = 1;
        return 0;
}

int freenect_stop_depth(freenect_device *dev)
{
        depth_running = 0;
        return 0;
}

int freenect_stop_video(freenect_device *dev)
{
        rgb_running = 0;
        return 0;
}

int freenect_set_video_format(freenect_device *dev, freenect_video_format fmt)
{
        assert(fmt == FREENECT_VIDEO_RGB);
        return 0;
}
int freenect_set_depth_format(freenect_device *dev, freenect_depth_format fmt)
{
        assert(fmt == FREENECT_DEPTH_11BIT);
        return 0;
}

void freenect_set_log_callback(freenect_context *ctx, freenect_log_cb cb) {}
void freenect_set_log_level(freenect_context *ctx, freenect_loglevel level) {}
int freenect_shutdown(freenect_context *ctx)
{
        return 0;
}
int freenect_close_device(freenect_device *dev)
{
        return 0;
}
int freenect_set_tilt_degs(freenect_device *dev, double angle)
{
        return 0;
}
int freenect_set_led(freenect_device *dev, freenect_led_options option)
{
        return 0;
}
int freenect_update_tilt_state(freenect_device *dev)
{
        return 0;
}

